package mirrormonkey.core.client;

import java.util.Collection;

import mirrormonkey.core.EntityLifecycleListener;
import mirrormonkey.framework.ConnectionInfo;
import mirrormonkey.framework.entity.EntityData;
import mirrormonkey.framework.entity.StaticEntityData;
import mirrormonkey.framework.entity.SyncEntity;
import mirrormonkey.framework.member.DynamicMemberData;

import com.jme3.network.MessageConnection;

public class ClientEntityData extends EntityData {

	protected StaticEntityData staticData;

	protected DynamicMemberData[] dynamicMembers;

	protected final ClientCoreModule module;

	public ClientEntityData(int id, SyncEntity entity,
			ClientCoreModule coreModule) {
		super(id, entity);
		this.module = coreModule;
	}

	public final void setStaticData(StaticEntityData staticData) {
		if (this.staticData == staticData) {
			return;
		}
		if (this.staticData != null) {
			this.staticData.removeEntity(this);
		}
		if (staticData != null) {
			staticData.addEntity(this);
			dynamicMembers = staticData.createDynamicMemberData();
		} else {
			dynamicMembers = null;
		}
		this.staticData = staticData;
	}

	@Override
	protected void destroy() {
		if (isRegistered()) {
			if (staticData != null) {
				staticData.removeEntity(this);
			}
			module.getEntityProvider().removeData(this);
			if (entity != null) {
				entity.setData(null);
			}
			registered = false;
		}
	}

	@Override
	public void addEntityLifecycleListener(EntityLifecycleListener listener) {
		module.getEntityProvider().assertNotOutdated(this);
		if (!isRegistered()) {
			module.getEntityProvider().registerData(this);
			registered = true;
		}
		super.addEntityLifecycleListener(listener);
	}

	@Override
	public void removeEntityLifecycleListener(EntityLifecycleListener listener) {
		module.getEntityProvider().assertNotOutdated(this);
		if (isRegistered() && !isEntityPresent()) {
			destroy();
			registered = false;
		}
		super.removeEntityLifecycleListener(listener);
	}

	@Override
	public final StaticEntityData getStaticData(MessageConnection forConnection) {
		return staticData;
	}

	@Override
	public final DynamicMemberData[] getMemberData(StaticEntityData staticData) {
		return dynamicMembers;
	}

	@Override
	public final Collection<ConnectionInfo> getConnections(
			StaticEntityData staticData) {
		return module.getConnectionInfoAsCollection();
	}

	public void referenceArrived(SyncEntity reference,
			StaticEntityData staticData) {
		setEntity(reference);
		reference.setData(this);
		setStaticData(staticData);
		if (!isRegistered()) {
			module.getEntityProvider().registerData(this);
			registered = true;
		}
	}

	public void referenceDeparted() {
		module.notifyEndListeners(this, staticData, module.connectionInfo);
		entity.setData(null);
		setEntity(null);
		setStaticData(null);
		if (isRegistered() && getListenerConfiguration().isEmpty()) {
			destroy();
			registered = false;
		}
	}

	protected void newReferenceArrived(SyncEntity newReference) {
		setEntity(newReference);
		newReference.setData(this);
	}

}
